package baseStructure;

/***
 * @author Ragnvald Fuglestein
 */

import java.io.Serializable;

public final class Artist extends Base implements Serializable {
	private static final long serialVersionUID = -1350136600298345912L;
	
	private final SortedList<Album> albums = new SortedList<>(8, 4);
	private final SortedList<Track> tracks = new SortedList<>(10, 10);

	public Artist(final String name) {
		super(name);
	}

	/***
	 * Add album if it is not already added
	 * @return true if the list changed
	 */
	public final boolean addAlbum(final Album album) {
		if (!albums.contains(album)) {
			albums.add(album);
			album.setArtist(this);
			return true;
		}
		return false;
	}

	/***
	 * Remove album if exists
	 * @return true if the list changed
	 */
	public final boolean removeAlbum(final Album album) {
		return albums.remove(album);
	}

	/***
	 * 
	 * @return albums
	 */
	public final SortedList<Album> getAlbums() {
		return albums;
	}
	
	/***
	 * 
	 * Add albums matching search to list 
	 * @param list search
	 */
	public final void getAlbums(SortedList<Album> list, SearchAlbum search) {
		for (Album album : albums) {
			if (search.matches(album)) {
				list.add(album);
			}
		}
	}

	/***
	 * 
	 * @param search
	 * @return first album to match search
	 */
	/*public final Album getAlbum(final SearchAlbum search) {
		return albums.search(search);
	}*/

	/***
	 * Adds tracks matching search to list
	 * @param list search
	 */
	public final void getTracks(final SortedList<Track> list, final SearchTrack search) {
		SearchAlbum searchalbum;
		
		if ((searchalbum = search.getSearchAlbum()) != null) {
			SortedList<Album> al = new SortedList<>();
			albums.getMatch(al, searchalbum);
			
			for (Album album : al) {
				album.getTracks(list, search);
			}
		} else {
			for (Album a : albums) {
				a.getTracks(list, search);
			}
			tracks.getMatch(list, search);
		}
	}
	
	/***
	 * 
	 * @return true if list changed
	 */
	public final boolean addTrack(final Track track) {
		if (!this.tracks.contains(track)) {
			this.tracks.add(track);
			track.setAlbum(null);
			track.setArtist(this);
			return true;
		}
		return false;
	}

	/***
	 * 
	 * @return true if list changed
	 */
	public final boolean removeTrack(final Track track) {
		return tracks.remove(track);
	}

	/***
	 * 
	 * @return List of tracks without associated albums
	 */
	public SortedList<Track> getTracks() {
		return this.tracks;
	}
	
	/***
	 * Merge all albums and tracks from artist to this.
	 * @param artist
	 */
	public final boolean merge(final Artist artist) { //TODO: Rewrite to use a generic compare method to compare based on all names.
		SortedList<Album> al = new SortedList<>();
		for (Album album : artist.getAlbums()) {
			getAlbums(al, album.toSearch());
			if (al.size() > 0) {
				for (Album a : al) {
					a.merge(album);
				}
			} else {
				addAlbum(album);
			}
			al.clear();
		}
		SortedList<Track> tl = new SortedList<>();
		for (Track t : artist.getTracks()) {
			tracks.getMatch(tl, t.toSearch());
			if (tl.size() > 0) {
				for (Track t2 : tl) {
					t2.merge(t);
				}
			} else {
				tracks.add(t);
			}
			tl.clear();
		}
		
		return super.merge(artist);
	}
	
	public String toString() {
		return getName();
	}

	/***
	 * 
	 * @return SearchArtist with name set
	 */
	public SearchArtist toSearch() {
		return new SearchArtist(getName());
	}
	
	public String getInfo() {
		String ret = "";
		
		ret += "Artist name: " + getName() + "\n";
		ret += super.getInfo();
		return ret;
	}
}
